package com.qingzhuge.controller.base;

import com.google.common.collect.Lists;
import com.qingzhuge.common.DateFormat;
import com.qingzhuge.common.HttpCode;
import com.qingzhuge.common.utils.WebUtil;
import com.qingzhuge.common.DtoConverter;
import com.qingzhuge.dto.response.ResponseBodyDto;
import com.qingzhuge.interfaces.ISysUser;
import com.qingzhuge.utils.PageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;


/**
 * @author : zero.xiao
 * @description : 控制器基类
 * @modified :
 */
public abstract class AbstractController {
    protected Logger log = LoggerFactory.getLogger(this.getClass());
    @Resource
    protected HttpServletRequest request;

    @Resource
    protected HttpServletResponse response;

    @Resource
    protected HttpSession session;

    private static ThreadLocal<Long> uid = new ThreadLocal<>();
    private static ThreadLocal<String> openId = new ThreadLocal<>();
    private static ThreadLocal<String> username = new ThreadLocal<>();

    public static void setUid(Long uid) {
        AbstractController.uid.set(uid);
    }

    public static void setOpenId(String openId) {
        AbstractController.openId.set(openId);
    }

    public static void setUsername(String username) {
        AbstractController.username.set(username);
    }

    protected Long getUid() {
        return uid.get();
    }

    protected String getOpenId() {
        return openId.get();
    }

    protected String getUsername() {
        return username.get();
    }

    protected ISysUser getCurrUser() {
        return WebUtil.getSysUser();
    }

    /**
     * 当前登录用户id
     *
     * @return Long
     */
    protected Long getUserId() {
        return WebUtil.getSysUserId();
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new DateFormat(), true));
    }

    @PreDestroy
    protected void destroy() {
        uid.remove();
        openId.remove();
    }

    protected <ResD, T> ResD doBean2Dto(T bean, Class<? extends ResD> resDtoClass) {
        return new DtoConverter() {
        }.doBackward(bean, resDtoClass);
    }

    protected <ReqD, T> T doDto2Bean(ReqD dto, Class<? extends T> beanClass) {
        return new DtoConverter() {
        }.doForward(dto, beanClass);
    }

    /**
     * 分布对象转分布返回对象
     */
    protected <ResD, T> ResponseEntity<ResponseBodyDto<PageUtil<ResD>>> returnSuccess(PageUtil<T> page, Class<? extends ResD> resDtoClass) {

        List<ResD> content = Lists.newArrayList();
        page.getContent().forEach(bean -> content.add(doBean2Dto(bean, resDtoClass)));
        PageUtil<ResD> pageUtil = PageUtil.of(
                page.getTotal(),
                page.getSize(),
                page.getPage(),
                page.getPageTotal(),
                page.isFirst(),
                page.isLast(),
                content);
        return returnSuccess(pageUtil);
    }


    protected <ResD, T> ResponseEntity<ResponseBodyDto<ResD>> returnSuccess(T bean, Class<? extends ResD> resDtoClass) {
        return returnSuccess(doBean2Dto(bean, resDtoClass));
    }

    /**
     * 设置成功响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnSuccess() {
        return returnSuccess(null);
    }


    /**
     * 设置成功响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnSuccess(P data) {
        return returnResult(HttpCode.OK, data);
    }

    /**
     * 设置成功响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnSuccess(HttpCode code, P data) {
        return returnResult(code.value(), code.message(), data, HttpStatus.OK);
    }

    /**
     * 设置成功响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnSuccess(Integer code, String msg) {
        return returnResult(code, msg, null, HttpStatus.OK);
    }

    /**
     * 设置成功响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnSuccess(Integer code, String msg, P data) {
        return returnResult(code, msg, data, HttpStatus.OK);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(String msg) {
        return returnFailed(msg, null);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(String msg, P data) {
        return returnResult(HttpCode.VALIDATOR_FAILED.value(), msg, data, HttpStatus.OK);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(HttpCode code) {
        return returnFailed(code, null);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(HttpCode code, P data) {
        return returnResult(code.value(), code.message(), data, HttpStatus.OK);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(Integer code, String msg, P data) {
        return returnResult(code, msg, data, HttpStatus.OK);
    }

    /**
     * 设置响应代码
     */
    protected <P> ResponseEntity<ResponseBodyDto<P>> returnFailed(Integer code, String msg, P data, HttpStatus status) {
        return returnResult(code, msg, data, status);
    }

    /**
     * 设置响应代码
     */
    private <P> ResponseEntity<ResponseBodyDto<P>> returnResult(HttpCode code, P data) {
        return returnResult(code.value(), code.message(), data, HttpStatus.OK);
    }

    private <P> ResponseEntity<ResponseBodyDto<P>> returnResult(Integer code, String msg, P data, HttpStatus status) {
        ResponseBodyDto<P> resBody = ResponseBodyDto
                .<P>builder()
                .data(data)
                .code(code)
                .message(msg)
                .build();
        if (null == status) {
            status = HttpStatus.OK;
        }
        ResponseEntity.BodyBuilder builder = ResponseEntity.status(status);
        return builder.body(resBody);
    }
}
